import java.util.Random;

import EnumerationPackage.ActionCode;
import EnumerationPackage.EventID;
import EventPackage.Event;
import EventPackage.EventManagerInterface;
import EventPackage.EventQueue;
import InstrumentationPackage.Indicator;
import InstrumentationPackage.MessageWindow;


public class SecuritySensor {
	public static void main(String args[])
	{
		String EvtMgrIP;					// Event Manager IP address
		Event Evt = null;					// Event object
		EventQueue eq = null;				// Message Queue
		int EvtId = 0;						// User specified event ID
		EventManagerInterface em = null;	// Interface object to the event manager
		boolean Armed = false;				// Security armed state: false == disarmed, true == armed
		int	Delay = 2500;					// The loop delay (2.5 seconds)
		boolean Done = false;				// Loop termination flag


		
		/////////////////////////////////////////////////////////////////////////////////
		// Get the IP address of the event manager
		/////////////////////////////////////////////////////////////////////////////////

 		if ( args.length == 0 )
 		{
			// event manager is on the local system

			System.out.println("\n\nAttempting to register on the local machine..." );

			try
			{
				// Here we create an event manager interface object. This assumes
				// that the event manager is on the local machine

				em = new EventManagerInterface();
			}

			catch (Exception e)
			{
				System.out.println("Error instantiating event manager interface: " + e);

			} // catch

		} else {

			// event manager is not on the local system

			EvtMgrIP = args[0];

			System.out.println("\n\nAttempting to register on the machine:: " + EvtMgrIP );

			try
			{
				// Here we create an event manager interface object. This assumes
				// that the event manager is NOT on the local machine

				em = new EventManagerInterface( EvtMgrIP );
			}

			catch (Exception e)
			{
				System.out.println("Error instantiating event manager interface: " + e);

			} // catch

		} // if

		// Here we check to see if registration worked. If em is null then the
		// event manager interface was not properly created.

		if (em != null)
		{
			System.out.println("Registered with the event manager.");
			// We create a message window. Note that we place this panel about 1/2 across 
			// and 2/3s down the screen
			
			float WinPosX = 0.5f; 	//This is the X position of the message window in terms 
									//of a percentage of the screen height
			float WinPosY = 0.60f;	//This is the Y position of the message window in terms 
								 	//of a percentage of the screen height 
			
			MessageWindow mw = new MessageWindow("Security Sensor", WinPosX, WinPosY);

			mw.WriteMessage("Registered with the event manager." );

	    	try
	    	{
				mw.WriteMessage("   Participant id: " + em.GetMyId() );
				mw.WriteMessage("   Registration Time: " + em.GetRegistrationTime() );

			} // try

	    	catch (Exception e)
			{
				mw.WriteMessage("Error:: " + e);

			} // catch

			mw.WriteMessage("\nInitializing Security Simulation::" );

			/********************************************************************
			** Here we start the main simulation loop
			*********************************************************************/

			mw.WriteMessage("Beginning Simulation... ");


			while ( !Done )
			{

				// Get the message queue

				try
				{
					eq = em.GetEventQueue();

				} // try

				catch( Exception e )
				{
					mw.WriteMessage("Error getting event queue::" + e );

				} // catch

				// If there are messages in the queue, we read through them.
				// We are looking for EventIDs = SEC_CONFIRM, this means the the security system
				// has been turned armed/disarmed. Note that we get all the messages
				// from the queue at once... there is a 2.5 second delay between samples,..
				// so the assumption is that there should only be a message at most.
				// If there are more, it is the last message that will effect the
				// output of the security system as it would in reality.

				int qlen = eq.GetSize();

				for ( int i = 0; i < qlen; i++ )
				{
					Evt = eq.GetEvent();

					if ( Evt.GetEventId() == EventID.SEC_CONFIRM.getEventIdNum() )
					{
						mw.WriteMessage("Received security event");
						if (Evt.GetMessage().equalsIgnoreCase(ActionCode.SECURITY_ARMED.getCode())) // security armed
						{
							mw.WriteMessage("Security system armed");
							Armed = true;

						} // if

						else if (Evt.GetMessage().equalsIgnoreCase(ActionCode.SECURITY_DISARMED.getCode())) // security disarmed
						{
							mw.WriteMessage("Security system disarmed");
							Armed = false;

						} // if

					} // if

					// If the event ID == 99 then this is a signal that the simulation
					// is to end. At this point, the loop termination flag is set to
					// true and this process unregisters from the event manager.

					else if ( Evt.GetEventId() == EventID.DONE.getEventIdNum() )
					{
						Done = true;

						try
						{
							em.UnRegister();

				    	} // try

				    	catch (Exception e)
				    	{
							mw.WriteMessage("Error unregistering: " + e);

				    	} // catch

				    	mw.WriteMessage("\n\nSimulation Stopped. \n");

					} // if

				} // for

				// Now we simulate security events according to the armed status

				if (Armed)
				{
					switch (randomZeroToTwo()){
					case 0:
						//security event occurs
						
						switch (randomZeroToTwo()){
						case 0:
							mw.WriteMessage("\nDoor break!\n");
							PostSecEvent(em, ActionCode.DOOR_BROKEN.getCode());
							break;
						case 1:
							mw.WriteMessage("\nWindow break!\n");
							PostSecEvent(em, ActionCode.WINDOW_BROKEN.getCode());
							break;
						case 2:
							mw.WriteMessage("\nMotion detected!\n");
							PostSecEvent(em, ActionCode.MOTION_DETECTED.getCode());
							break;
						}
						break;
						default:
							//no security event, do nothing
							break;
					}

				} // if security armed

				try
				{
					Thread.sleep( Delay );

				} // try

				catch( Exception e )
				{
					mw.WriteMessage("Sleep error:: " + e );

				} // catch

			} // while

		} else {

			System.out.println("Unable to register with the event manager.\n\n" );

		} // if

	} // main
	
	/***************************************************************************
	* CONCRETE METHOD:: randomZeroToTwo
	* Purpose: This method provides a random zero to two to determine whether
	* a security event occurs, and which security event will occur. 
	*
	* Arguments: None.
	*
	* Returns: integer
	*
	* Exceptions: None
	*
	***************************************************************************/

	static private int randomZeroToTwo()
	{
		Random r = new Random();

		return(r.nextInt(3));

	} // CoinToss

	/***************************************************************************
	* CONCRETE METHOD:: PostSecEvent
	* Purpose: This method posts the specified security value to the
	* specified event manager. This method assumes an event ID specified in the enumeration.
	*
	* Arguments: EventManagerInterface ei - this is the eventmanger interface
	*			 where the event will be posted.
	*
	*			 String secEvtActionCode - the string representation of the 
	*			 security event action code
	*
	* Returns: none
	*
	* Exceptions: None
	*
	***************************************************************************/

	static private void PostSecEvent(EventManagerInterface ei, String secEvtActionCode )
	{
		// Here we create the event.

		Event evt = new Event( EventID.SEC.getEventIdNum(), secEvtActionCode );

		// Here we send the event to the event manager.

		try
		{
			ei.SendEvent( evt );
			//mw.WriteMessage( "Sent Security Event" );

		} // try

		catch (Exception e)
		{
			System.out.println( "Error Posting Security Event:: " + e );

		} // catch

	} // PostSecEvent
}
